package com.zihan.utils;

import cn.hutool.core.util.StrUtil;
import com.zihan.constant.RedisConstant;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

// 登录失败账号锁
@Component
public class AccountLockUtil {

    private static final Integer MAX_LOGIN_NUM = 5;  // 最大登录次数
    private static final Integer WAIT_TIME = 300;   // 等待时间(秒)
    private static final Integer CONTINUE_TIME = 30 * 60;  // 连续登录失败的值的保存时间(秒)

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 判断账户是否锁定，返回剩余锁定时间
     * @param account 用户账号
     * @return 剩余锁定时间(秒)，null表示未锁定
     */
    public Long accountIsLocked(String account) {
        //1、返回是否该账号被锁定
        String isLock = stringRedisTemplate.opsForValue().get(RedisConstant.LOGIN_FAIL_ACCOUNT_PREFIX + account);
        if (isLock != null) {
            Long expire = stringRedisTemplate.getExpire(RedisConstant.LOGIN_FAIL_ACCOUNT_PREFIX + account);
            // 返回剩余冻结时间
            return expire;
        }
        return null;
    }

    /**
     * 记录登录失败并可能锁定账号
     * @param account 用户账号
     */
    public void lockAccount(String account) {
        // 1、用户登录失败，判断是否有值
        String isVal = stringRedisTemplate.opsForValue().get(RedisConstant.LOGIN_ACCOUNT_PREFIX + account);
        if (StrUtil.isEmpty(isVal)) {
            // 没有值赋值1 并且设置过期时间
            stringRedisTemplate.opsForValue().set(RedisConstant.LOGIN_ACCOUNT_PREFIX + account, "1", CONTINUE_TIME, TimeUnit.SECONDS);
            return;
        }
        Long number = stringRedisTemplate.opsForValue().increment(RedisConstant.LOGIN_ACCOUNT_PREFIX + account);

        // 判断是否五次,锁定账号
        if (number >= MAX_LOGIN_NUM) {
            // 先删除账号次数
            unlockAccount(account);
            // 锁定账号WAIT_TIME秒
            stringRedisTemplate.opsForValue().set(RedisConstant.LOGIN_FAIL_ACCOUNT_PREFIX + account, "LOCKED", WAIT_TIME, TimeUnit.SECONDS);
        }
    }

    /**
     * 登录成功后重置失败计数
     * @param account 用户账号
     */
    public void unlockAccount(String account) {
        stringRedisTemplate.delete(RedisConstant.LOGIN_ACCOUNT_PREFIX + account);
    }
}